// pages/index/index.js
const ApiClient = require('../../utils/api');

Page({
  data: {
    examName: 'CET-6',
    daysLeft: 28,
    examDate: '2025年12月21日',
    selectedTimeSlot: '', // 初始为空，由 updateTimeSlot 方法设置
    motivationQuote: '"坚持是成功的阶梯，今天的努力是明天的收获"',
    activeTab: 'study',
    selectedStartTime: '14:00',
    selectedEndTime: '18:00',
    startAngle: 210, // 14:00 对应的角度 (14*60/30*7.5=210)
    endAngle: 270,   // 18:00 对应的角度 (18*60/30*7.5=270)
    studyDuration: '4.0', // 学习时长（小时）
    isDragging: false,
    dragType: '', // 'start' 或 'end'
    
    // 时间槽信息
    timeSlotInfo: null, // 存储时间槽显示信息
    
    // 匹配池相关状态
    isMatching: false, // 是否正在匹配
    matchingTime: '00:00', // 匹配倒计时
    matchingSeconds: 0, // 匹配秒数
    isMatchSuccess: false, // 是否匹配成功
    currentTimeSlotKey: "", // 当前匹配的时间槽键值
    matchRecordId: "", // 匹配成功后的记录ID
    studyRecordId: null, // 学习记录ID
    studyGoal: null, // 学习目标
    goalDaysLeft: 0, // 学习目标剩余天数
    // 目标弹窗相关数据
    showGoalModal: false,
    tempGoalTitle: '',
    tempGoalDeadline: '',
    isEditingGoal: false,
    existingGoalData: null,
    currentUser: {
      name: '小明同学',
      avatar: '/static/icons/avatar-placeholder.png',
      isOnline: true,
      examName: 'CET-6',
      daysLeft: 28,
      examDate: '2025年12月21日'
    },
    matchedUser: {
      name: '小红同学',
      avatar: '/static/icons/avatar-placeholder.png',
      isOnline: true,
      examName: 'CET-6',
      daysLeft: 32,
      examDate: '2025年12月21日'
    }
  },

  onLoad(options) {
    // 检查登录状态
    this.checkLoginStatus();
    
    // 页面加载时的逻辑
    this.setDefaultTime(); // 这个方法内部会调用 updateTimeSlot()
    this.calculateDaysLeft();
    this.calculateStudyDuration();
    
    // 延迟绘制，确保数据已更新
    setTimeout(() => {
      this.drawTimeCircle();
    }, 100);
    
    // 获取学习目标
    this.getStudyGoal();
    
    // 覆盖当前用户头像/昵称为本地缓存中的真实值
    this.applyCurrentUserFromCache();
    
    // 设置导航栏标题
    wx.setNavigationBarTitle({
      title: '督搭'
    });
  },
  
  // 计算学习目标剩余天数
  calculateGoalDaysLeft() {
    if (this.data.studyGoal && this.data.studyGoal.deadline) {
      const deadlineDate = new Date(this.data.studyGoal.deadline);
      const today = new Date();
      today.setHours(0, 0, 0, 0); // 设置为当天开始时间
      deadlineDate.setHours(0, 0, 0, 0); // 设置为截止日期开始时间
      const timeDiff = deadlineDate.getTime() - today.getTime();
      const daysLeft = Math.ceil(timeDiff / (1000 * 3600 * 24));
      
      this.setData({
        goalDaysLeft: daysLeft > 0 ? daysLeft : 0
      });
    }
  },

  onReady() {
    // 页面初次渲染完成
    this.drawTimeCircle();
  },

  onShow() {
    // 检查登录状态
    this.checkLoginStatus();
    
    // 获取学习目标
    this.getStudyGoal();
    
    // 页面显示
    // 设置导航栏标题
    wx.setNavigationBarTitle({
      title: '督搭'
    });
    
    // 检查是否有学习记录，该函数会负责在状态更新后重新渲染UI
    this.checkStudyRecord();
    // 启动在线状态心跳（本账号）
    console.log('onShow: startOnlineHeartbeat');
    try { this.startOnlineHeartbeat(); } catch (e) { console.warn('startOnlineHeartbeat failed:', e); }
  },


  // 检查学习记录
  async checkStudyRecord() {
    try {
      console.log('检查是否有活跃的学习记录');

      const result = await wx.cloud.callFunction({
        name: 'getStudyRecord',
        data: {} // 不传递studyRecordId，让云函数查询最新记录
      });

      console.log('getStudyRecord返回结果:', result.result);

      if (result.result.code === 0 && result.result.data) {
        const studyRecord = result.result.data;

        // 确保学习伙伴信息存在
        let partnerInfo = studyRecord.partnerInfo || {};
        if (!partnerInfo.nickName) {
          partnerInfo = {
            nickName: '学习伙伴',
            avatarUrl: '/static/icons/avatar-placeholder.png',
            ...partnerInfo
          };
        }

        // 显示开始学习卡片
        // 先将头像从 cloud:// 转为临时 https，再写入数据，避免首帧渲染 500
        const avatarRaw = this.normalizeAvatar(partnerInfo.avatarUrl || partnerInfo.avatar_url || partnerInfo.avatar);
        let avatar = '';
        try {
          avatar = await this.ensureHttpsAvatar(avatarRaw);
        } catch (e) {
          console.warn('ensureHttpsAvatar 转换失败:', e);
        }
        if (
          !(
            typeof avatar === 'string' &&
            (/^https?:\/\//i.test(avatar) ||
              avatar.indexOf('wxfile://') === 0 ||
              avatar.indexOf('/static/') === 0 ||
              avatar.indexOf('data:') === 0)
          )
        ) {
          avatar = '/static/icons/avatar-placeholder.png';
        }
        this.setData({
          isMatchSuccess: true,
          isMatching: false,
          studyRecordId: studyRecord.studyRecordId,
          matchId: studyRecord.matchId || studyRecord.matchRecordId || null,
          selectedStartTime: studyRecord.startTime || this.data.selectedStartTime,
          selectedEndTime: studyRecord.endTime || this.data.selectedEndTime,
          studyDuration: studyRecord.duration || this.data.studyDuration,
          matchedUser: {
            name: partnerInfo.nickName || partnerInfo.nickname || '学习伙伴',
            avatar: avatar,
            isOnline: true,
            examName: 'CET-6',
            daysLeft: 28,
            examDate: '2025年12月21日'
          }
        });


        // 兜底：若对方昵称/头像不全，且有 partnerId，则云端拉取补全
        this.ensurePartnerInfoCompleteness(studyRecord);
        // 基于 matchId 的兜底：查询对端学习记录再取对方资料（带重试）
        if (studyRecord.matchId) {
          this.ensurePeerInfoByMatchIdWithRetry(studyRecord.matchId);
        }

        console.log('找到学习记录，显示开始学习卡片，studyRecordId:', studyRecord.studyRecordId);
      } else {
        // 没有学习记录，重置为未匹配状态
        this.setData({
          isMatchSuccess: false,
          isMatching: false,
          studyRecordId: null,
          matchId: null,
          matchingTime: '00:00',
          matchingSeconds: 0
        });

        console.log('没有学习记录，重置为未匹配状态');
      }
    } catch (error) {
      console.error('检查学习记录出错:', error);
      // 出错时重置为未匹配状态
      this.setData({
        isMatchSuccess: false,
        isMatching: false,
        studyRecordId: null,
        matchId: null
      });
    } finally {
      // 无论成功与否，都在状态更新后重新渲染UI
      // 使用 nextTick 确保 setData 完成后执行
      wx.nextTick(() => {
        console.log('状态检查完成，重新渲染时间选择器');
        this.syncTimeAndAngle(); // 同步时间和角度
        this.drawTimeCircle(); // 重新绘制时间圆环
      });
    }
  },

  onHide() {
    // 页面隐藏时不取消匹配，让匹配在后台继续进行
    // 只清除前端计时器，保持匹配状态
    if (this.matchingTimer) {
      clearInterval(this.matchingTimer);
      this.matchingTimer = null;
    }
    // 停止本账号在线心跳
    if (this.onlinePingTimer) {
      console.log('onHide: stopOnlineHeartbeat, timer=', this.onlinePingTimer);
      clearInterval(this.onlinePingTimer);
      this.onlinePingTimer = null;
    } else {
      console.log('onHide: stopOnlineHeartbeat skipped (no timer)');
    }
  },

  // 处理导航栏返回按钮
  onNavigationBarBackTap() {
    wx.navigateBack();
  },

  // 设置默认时间（当前时间的下一个半点作为开始，再加1小时作为结束）
  setDefaultTime() {
    const now = new Date();
    const currentHour = now.getHours();
    const currentMinute = now.getMinutes();
    
    // 计算下一个半点时间
    let startHour = currentHour;
    let startMinute = 0;
    
    if (currentMinute < 30) {
      startMinute = 30;
    } else {
      startHour = (currentHour + 1) % 24;
      startMinute = 0;
    }
    
    // 结束时间为开始时间加1小时
    let endHour = (startHour + 1) % 24;
    let endMinute = startMinute;
    
    // 格式化时间字符串
    const startTime = `${startHour.toString().padStart(2, '0')}:${startMinute.toString().padStart(2, '0')}`;
    const endTime = `${endHour.toString().padStart(2, '0')}:${endMinute.toString().padStart(2, '0')}`;
    
    // 计算对应的角度
    const startAngle = this.timeToAngle(startTime);
    const endAngle = this.timeToAngle(endTime);
    
    // 更新数据
    this.setData({
      selectedStartTime: startTime,
      selectedEndTime: endTime,
      startAngle: startAngle,
      endAngle: endAngle
    });
    
    // 使用 determineTimeSlot 生成正确的显示文本
    this.updateTimeSlot();
  },

  // 计算考试剩余天数
  calculateDaysLeft() {
    const examDate = new Date('2025-12-21');
    const today = new Date();
    const timeDiff = examDate.getTime() - today.getTime();
    const daysLeft = Math.ceil(timeDiff / (1000 * 3600 * 24));
    
    this.setData({
      daysLeft: daysLeft > 0 ? daysLeft : 0
    });
  },

  // 头像地址规范化，避免历史 /assets 路径导致 500
  normalizeAvatar(url) {
    if (!url) return '/static/icons/avatar-placeholder.png';
    if (typeof url === 'string' && url.indexOf('/assets/') === 0) {
      return '/static/icons/avatar-placeholder.png';
    }
    return url;
  },

  // 将 avatar 规范化为可显示的 https/本地占位图；支持以下策略：
  // - https 非 tcb：原样返回
  // - https 为 tcb 临时链接：尝试解析为 fileID 并刷新新的临时 https
  // - cloud://：转临时 https
  // - 其余：占位图
  async ensureHttpsAvatar(avatar) {
    try {
      const placeholder = '/static/icons/avatar-placeholder.png';
      if (!avatar || typeof avatar !== 'string') return placeholder;

      // 已是网络/本地格式
      if (/^https?:\/\//i.test(avatar) || avatar.indexOf('data:') === 0 || avatar.indexOf('/static/') === 0 || avatar.indexOf('wxfile://') === 0) {
        // 若是 tcb 临时链接，尝试刷新为最新的临时链接
        if (/^https?:\/\/[^/]+\.tcb\.qcloud\.la\//i.test(avatar)) {
          try {
            const m = avatar.match(/^https?:\/\/([^\/]+)\.tcb\.qcloud\.la\/([^?]+)(?:\?|$)/i);
            if (m && m[1] && m[2]) {
              const hostPrefix = m[1];  // 形如 cloud1-xxxxx-xxxxxxxx
              const path = m[2];        // 形如 user_avatars/xxx.jpeg
              const fileID = 'cloud://' + hostPrefix + '/' + path;
              const tf = await wx.cloud.getTempFileURL({ fileList: [fileID] });
              const list = (tf && tf.fileList) || [];
              if (list[0] && list[0].tempFileURL) {
                return list[0].tempFileURL;
              }
            }
          } catch (eTcb) {
            console.warn('tcb https 刷新失败:', eTcb);
          }
        }
        // 其他 https/data:/wxfile:/static: 原样返回
        return avatar;
      }

      // cloud:// 转临时 https
      if (avatar.indexOf('cloud://') === 0) {
        try {
          const tf = await wx.cloud.getTempFileURL({ fileList: [avatar] });
          const list = (tf && tf.fileList) || [];
          if (list[0] && list[0].tempFileURL) {
            return list[0].tempFileURL;
          }
        } catch (e2) {
          console.warn('getTempFileURL 失败:', e2);
        }
        // 最终失败则使用占位
        return placeholder;
      }

      // 其它未知格式一律回退占位，避免 /pages/index/cloud://... 500
      return placeholder;
    } catch (e) {
      console.warn('ensureHttpsAvatar 转换失败:', e);
      return '/static/icons/avatar-placeholder.png';
    }
  },

  // 修复 matchedUser.avatar 为可显示的 https
  async fixMatchedUserAvatar() {
    try {
      const cur = (this.data.matchedUser && this.data.matchedUser.avatar) || '';
      const fixed = await this.ensureHttpsAvatar(cur);
      if (fixed && fixed !== cur) {
        this.setData({ 'matchedUser.avatar': fixed });
      }
    } catch (e) {
      console.warn('fixMatchedUserAvatar 失败:', e);
    }
  },

  // 从本地缓存覆盖当前用户展示信息（昵称/头像），兼容字段 nickName/nickname 与 avatarUrl/avatar_url
  async applyCurrentUserFromCache() {
    try {
      const cached = wx.getStorageSync('userInfo') || null;
      if (!cached) return;
      const name = (cached.nickName || cached.nickname || cached.name || this.data.currentUser.name || '同学') + '';
      let avatar = this.normalizeAvatar(cached.avatarUrl || cached.avatar_url || cached.avatar || this.data.currentUser.avatar);
      // 若为 cloud:// 文件ID，先转为 https 临时链接，再写入，避免首帧 cloud:// 渲染 500
      if (typeof avatar === 'string' && avatar.indexOf('cloud://') === 0) {
        try {
          avatar = await this.ensureHttpsAvatar(avatar);
        } catch (e) {
          console.warn('ensureHttpsAvatar 转换失败:', e);
        }
      }
      this.setData({
        currentUser: Object.assign({}, this.data.currentUser, {
          name,
          avatar
        })
      });
    } catch (e) {
      console.warn('读取本地 userInfo 失败:', e);
    }
  },

  // 兜底：根据 partnerId 拉取匹配对方资料并覆盖 matchedUser
  async ensurePartnerInfoCompleteness(studyRecord) {
    try {
      const partnerId =
        (studyRecord && (studyRecord.partnerId || studyRecord.partnerOpenid || studyRecord.partnerOpenId || studyRecord.opponentOpenid || studyRecord.opponentId)) || '';
      if (!partnerId) return;

      const nameIsDefault = !this.data.matchedUser || !this.data.matchedUser.name || this.data.matchedUser.name === '学习伙伴';
      const avatarIsDefault =
        !this.data.matchedUser || !this.data.matchedUser.avatar || String(this.data.matchedUser.avatar).indexOf('avatar-placeholder') !== -1;
      // 如果头像是 tcb 临时URL（可能过期403），也应拉取一次云端资料进行覆盖
      const avatarLooksTempLink =
        !!(this.data.matchedUser && this.data.matchedUser.avatar && String(this.data.matchedUser.avatar).indexOf('tcb.qcloud.la') !== -1);
      if (!nameIsDefault && !avatarIsDefault && !avatarLooksTempLink) return;

      const res = await wx.cloud.callFunction({
        name: 'getUserInfo',
        data: { openid: partnerId }
      });
      if (res.result && res.result.code === 0 && res.result.data) {
        const info = res.result.data;
        const name = info.nickName || info.nickname || this.data.matchedUser.name || '学习伙伴';
        let avatar = this.normalizeAvatar(info.avatarUrl || info.avatar_url || info.avatar || this.data.matchedUser.avatar);
        try {
          avatar = await this.ensureHttpsAvatar(avatar);
        } catch (e) {
          console.warn('ensurePartnerInfoCompleteness avatar 转换失败:', e);
        }
        this.setData({
          'matchedUser.name': name,
          'matchedUser.avatar': avatar
        });
      }
    } catch (e) {
      console.warn('ensurePartnerInfoCompleteness 失败:', e);
    }
  },



  // 匹配对方头像加载日志（便于排查实际 URL 与失败原因）
  onMatchedAvatarError(e) {
    const url = (e && e.currentTarget && e.currentTarget.dataset && e.currentTarget.dataset.avatar) || '';
    const err = (e && e.detail && e.detail.errMsg) || '';
    console.warn('matchedUser avatar load error:', err, 'url:', url);
  },

  onMatchedAvatarLoad(e) {
    const url = (e && e.currentTarget && e.currentTarget.dataset && e.currentTarget.dataset.avatar) || '';
    console.log('matchedUser avatar loaded:', url);
  },

  // 当前用户头像加载失败兜底（从本地缓存恢复，必要时云端刷新，再回退占位）
  async onCurrentAvatarError(e) {
    try {
      const url = (e && e.currentTarget && e.currentTarget.dataset && e.currentTarget.dataset.avatar) || '';
      const err = (e && e.detail && e.detail.errMsg) || '';
      console.warn('currentUser avatar load error:', err, 'url:', url);

      const placeholder = '/static/icons/avatar-placeholder.png';
      const cached = wx.getStorageSync('userInfo') || {};
      let raw = this.normalizeAvatar(cached.avatarUrl || cached.avatar_url || cached.avatar || this.data.currentUser.avatar);

      let next = placeholder;
      if (typeof raw === 'string') {
        if (raw.indexOf('cloud://') === 0) {
          try {
            next = await this.ensureHttpsAvatar(raw);
          } catch (e2) {
            console.warn('ensureHttpsAvatar(currentUser) 失败:', e2);
            next = placeholder;
          }
        } else if (/^https?:\/\//i.test(raw)) {
          // tcb 临时链接可能已过期，无法就地刷新，稍后尝试云端刷新
          if (raw.indexOf('tcb.qcloud.la') !== -1) {
            next = placeholder;
          } else {
            next = raw;
          }
        } else if (raw.indexOf('/static/') === 0 || raw.indexOf('wxfile://') === 0 || raw.indexOf('data:') === 0) {
          next = raw;
        } else {
          next = placeholder;
        }
      }

      // 二级兜底：若仍为占位或命中 tcb 临时链接，尝试从云端拉取当前用户头像源并刷新
      if (!next || next === placeholder || (typeof next === 'string' && next.indexOf('tcb.qcloud.la') !== -1)) {
        try {
          const res = await wx.cloud.callFunction({ name: 'getUserInfo', data: {} });
          if (res && res.result && res.result.code === 0 && res.result.data) {
            const info = res.result.data;
            let fresh = this.normalizeAvatar(info.avatarUrl || info.avatar_url || info.avatar);
            try {
              fresh = await this.ensureHttpsAvatar(fresh);
            } catch (e3) {
              console.warn('ensureHttpsAvatar(fresh) 失败:', e3);
            }
            if (
              typeof fresh === 'string' &&
              (/^https?:\/\//i.test(fresh) ||
                fresh.indexOf('wxfile://') === 0 ||
                fresh.indexOf('/static/') === 0 ||
                fresh.indexOf('data:') === 0)
            ) {
              next = fresh;
              console.log('currentUser avatar refreshed from cloud:', next);
            }
          }
        } catch (eCloud) {
          console.warn('getUserInfo fallback 失败:', eCloud);
        }
      }

      this.setData({ 'currentUser.avatar': next });
    } catch (ex) {
      console.warn('onCurrentAvatarError 处理失败:', ex);
      this.setData({ 'currentUser.avatar': '/static/icons/avatar-placeholder.png' });
    }
  },

  onCurrentAvatarLoad(e) {
    const url = (e && e.currentTarget && e.currentTarget.dataset && e.currentTarget.dataset.avatar) || '';
    console.log('currentUser avatar loaded:', url);
  },

  // 启动本账号在线心跳（每60s一次）
  startOnlineHeartbeat() {
    try {
      const thresholdMs = 60000;
      if (this.onlinePingTimer) {
        console.log('startOnlineHeartbeat: clear existing timer', this.onlinePingTimer);
        clearInterval(this.onlinePingTimer);
        this.onlinePingTimer = null;
      }
      console.log('startOnlineHeartbeat: init, thresholdMs=', thresholdMs);
      const ping = async () => {
        try {
          console.log('online ping: tick');
          const res = await wx.cloud.callFunction({
            name: 'getUserInfo',
            data: { ping: true, onlineThresholdMs: thresholdMs }
          });
          const d = res && res.result && res.result.data;
          console.log('online ping: result', d && d.isOnline, d);
          if (d && typeof d.isOnline === 'boolean') {
            const prev = this.data && this.data.currentUser && this.data.currentUser.isOnline;
            if (prev !== d.isOnline) {
              console.log('online status changed:', prev, '->', d.isOnline);
            }
            this.setData({ 'currentUser.isOnline': d.isOnline });
          }
        } catch (e) {
          console.warn('online ping failed:', e);
        }
      };
      ping();
      this.onlinePingTimer = setInterval(ping, thresholdMs);
      console.log('startOnlineHeartbeat: timer started', this.onlinePingTimer);
    } catch (e) {
      console.warn('startOnlineHeartbeat failed:', e);
    }
  },

  // 停止在线心跳
  stopOnlineHeartbeat() {
    if (this.onlinePingTimer) {
      clearInterval(this.onlinePingTimer);
      this.onlinePingTimer = null;
    }
  },

  // 计算学习时长
  calculateStudyDuration() {
    const startTime = this.data.selectedStartTime;
    const endTime = this.data.selectedEndTime;
    
    // 解析时间
    const [startHour, startMin] = startTime.split(':').map(Number);
    const [endHour, endMin] = endTime.split(':').map(Number);
    
    // 转换为分钟
    const startMinutes = startHour * 60 + startMin;
    let endMinutes = endHour * 60 + endMin;
    
    // 如果结束时间小于等于开始时间，说明跨天了，加上24小时
    if (endMinutes <= startMinutes) {
      endMinutes += 24 * 60; // 加上24小时
    }
    
    // 计算时长（分钟）
    let durationMinutes = endMinutes - startMinutes;
    
    // 限制最大学习时长为18小时（1080分钟）
    const maxDurationMinutes = 18 * 60; // 18小时 = 1080分钟
    if (durationMinutes > maxDurationMinutes) {
      durationMinutes = maxDurationMinutes;
      
      // 重新计算结束时间，确保不超过18小时
      const newEndMinutes = startMinutes + maxDurationMinutes;
      const newEndHour = Math.floor(newEndMinutes / 60) % 24;
      const newEndMin = newEndMinutes % 60;
      const newEndTime = `${String(newEndHour).padStart(2, '0')}:${String(newEndMin).padStart(2, '0')}`;
      
      // 更新结束时间和对应的角度
      this.setData({
        selectedEndTime: newEndTime,
        endAngle: this.timeToAngle(newEndTime)
      });
      
      // 重新绘制时间圆盘
      this.drawTimeCircle();
      
      // 提示用户
      wx.showToast({
        title: '学习时长已限制在18小时内',
        icon: 'none',
        duration: 2000
      });
    }
    
    // 转换为小时，保留一位小数
    const durationHours = (durationMinutes / 60).toFixed(1);
    
    this.setData({
      studyDuration: durationHours
    });
  },

  // 同步时间和角度
  syncTimeAndAngle() {
    const startAngle = this.timeToAngle(this.data.selectedStartTime);
    const endAngle = this.timeToAngle(this.data.selectedEndTime);
    
    this.setData({
      startAngle: startAngle,
      endAngle: endAngle
    });
  },

  // 绘制时间选择圆环
  drawTimeCircle() {
    // 如果已经匹配成功，则不绘制圆环，避免因UI切换导致canvas节点找不到而报错
    if (this.data.isMatchSuccess) {
      console.log('已匹配成功，跳过绘制时间圆环');
      return;
    }
    
    console.log('开始绘制时间选择圆环');
    
    // 获取容器宽度作为canvas尺寸
    const query = wx.createSelectorQuery().in(this);
    query.select('.time-circle-wrapper').boundingClientRect();
    query.select('#timeCircle').node();
    query.exec((res) => {
      if (res[0] && res[1]) {
        console.log('成功获取Canvas元素和容器尺寸');
        const containerWidth = res[0].width;
        const outerDiameter = containerWidth - 32; // 圆环外直径 = 容器宽度 - 32px
        const innerDiameter = outerDiameter - 128; // 圆环内直径 = 外直径 - 128px
        const containerHeight = outerDiameter; // 容器高度 = 圆环外直径
        
        // 获取Canvas 2D上下文
        const canvas = res[1].node;
        const ctx = canvas.getContext('2d');
        
        // 设置canvas的实际绘制尺寸
        try {
          const dpr = wx.getWindowInfo().pixelRatio;
          canvas.width = outerDiameter * dpr;
          canvas.height = containerHeight * dpr;
          ctx.scale(dpr, dpr);
          
          const centerX = outerDiameter / 2;
          const centerY = outerDiameter / 2;
          const radius = outerDiameter / 2; // 外半径
          const innerRadius = innerDiameter / 2; // 内半径
          
          console.log('Canvas尺寸设置完成，开始绘制内容');
          this.drawCanvas(ctx, outerDiameter, containerHeight, centerX, centerY, radius, innerRadius);
        } catch (error) {
          console.error('Canvas绘制出错:', error);
        }
      } else {
        console.error('获取Canvas元素失败:', res);
        
        // 尝试延迟重试一次
        setTimeout(() => {
          console.log('延迟重试绘制时间选择圆环');
          const retryQuery = wx.createSelectorQuery().in(this);
          retryQuery.select('.time-circle-wrapper').boundingClientRect();
          retryQuery.select('#timeCircle').node();
          retryQuery.exec((retryRes) => {
            if (retryRes[0] && retryRes[1]) {
              console.log('重试成功获取Canvas元素');
              const containerWidth = retryRes[0].width;
              const outerDiameter = containerWidth - 32;
              const innerDiameter = outerDiameter - 128;
              const containerHeight = outerDiameter;
              
              const canvas = retryRes[1].node;
              const ctx = canvas.getContext('2d');
              
              try {
                const dpr = wx.getWindowInfo().pixelRatio;
                canvas.width = outerDiameter * dpr;
                canvas.height = containerHeight * dpr;
                ctx.scale(dpr, dpr);
                
                const centerX = outerDiameter / 2;
                const centerY = outerDiameter / 2;
                const radius = outerDiameter / 2;
                const innerRadius = innerDiameter / 2;
                
                this.drawCanvas(ctx, outerDiameter, containerHeight, centerX, centerY, radius, innerRadius);
              } catch (error) {
                console.error('重试Canvas绘制出错:', error);
              }
            } else {
              console.error('重试获取Canvas元素失败');
            }
          });
        }, 500);
      }
    });
  },

  // 实际绘制canvas内容
  drawCanvas(ctx, canvasWidth, canvasHeight, centerX, centerY, radius, innerRadius) {
    // 清空画布
    ctx.clearRect(0, 0, canvasWidth, canvasHeight);

    // 绘制背景圆环（主题色20%透明度）
    ctx.beginPath();
    ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI);
    ctx.arc(centerX, centerY, innerRadius, 0, 2 * Math.PI, true);
    ctx.fillStyle = 'rgba(138, 124, 254, 0.2)';
    ctx.fill('evenodd');

    // 绘制已选时间段圆环
    {
      // 设置颜色：匹配状态用绿色，正常状态用紫色
      ctx.fillStyle = this.data.isMatching ? '#4CAF50' : '#8A7CFE';
      
      // 转换角度：我们的角度系统是12点为0度，Canvas是3点为0度，需要减90度
      const startRad = (this.data.startAngle - 90) * Math.PI / 180;
      const endRad = (this.data.endAngle - 90) * Math.PI / 180;
    
      // 检查是否为24小时（开始和结束角度相等）
      if (this.data.startAngle === this.data.endAngle) {
        // 绘制整个圆环
        ctx.beginPath();
        ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI);
        ctx.arc(centerX, centerY, innerRadius, 0, 2 * Math.PI, true);
        ctx.closePath();
        ctx.fill();
      } else {
        // 绘制带圆角的选中时间段
        const ringWidth = radius - innerRadius;
        const capRadius = ringWidth / 2; // 圆角半径为圆环宽度的一半（50%圆角）
        
        // 计算圆环中心线的半径
        const middleRadius = (radius + innerRadius) / 2;
        
        // 计算起始和结束位置的坐标
        const startX = centerX + middleRadius * Math.cos(startRad);
        const startY = centerY + middleRadius * Math.sin(startRad);
        const endX = centerX + middleRadius * Math.cos(endRad);
        const endY = centerY + middleRadius * Math.sin(endRad);
        
        // 绘制主体圆环部分
        ctx.beginPath();
        ctx.arc(centerX, centerY, radius, startRad, endRad);
        ctx.arc(centerX, centerY, innerRadius, endRad, startRad, true);
        ctx.closePath();
        ctx.fill();
        
        // 绘制起始端的圆角
        ctx.beginPath();
        ctx.arc(startX, startY, capRadius, 0, 2 * Math.PI);
        ctx.fill();
        
        // 绘制结束端的圆角
        ctx.beginPath();
        ctx.arc(endX, endY, capRadius, 0, 2 * Math.PI);
        ctx.fill();
      }
    }

    // 绘制时间数字（从0开始每3小时显示一次，直到21h）
    for (let hour = 0; hour <= 21; hour += 3) {
      const timeStr = `${hour.toString().padStart(2, '0')}:00`;
      const angle = this.timeToAngle(timeStr); // 使用新的时间转角度方法
      const rad = (angle - 90) * Math.PI / 180; // 转换为Canvas坐标系统
      
      // 数字显示在圆环宽度中间位置
      const middleRadius = (radius + innerRadius) / 2;
      const textX = centerX + middleRadius * Math.cos(rad);
      const textY = centerY + middleRadius * Math.sin(rad);
      
      ctx.font = '14px sans-serif';
      ctx.fillStyle = '#333';
      ctx.textAlign = 'center';
      ctx.textBaseline = 'middle';
      ctx.fillText(hour.toString(), textX, textY);
    }

    // 绘制起始和结束点（圆环宽度中间位置）
    const drawHandle = (angle, color) => {
      const rad = (angle - 90) * Math.PI / 180; // 转换为Canvas坐标系统
      // 圆环宽度中间位置
      const handleRadius = (radius + innerRadius) / 2;
      const x = centerX + handleRadius * Math.cos(rad);
      const y = centerY + handleRadius * Math.sin(rad);
      
      // 绘制圆形手柄
      ctx.beginPath();
      ctx.arc(x, y, 8, 0, 2 * Math.PI);
      ctx.fillStyle = color;
      ctx.fill();
      ctx.strokeStyle = '#fff';
      ctx.lineWidth = 2;
      ctx.stroke();
    };

    // 绘制手柄（仅在非匹配状态下显示）
    if (!this.data.isMatching) {
      drawHandle(this.data.startAngle, '#8A7CFE');
      drawHandle(this.data.endAngle, '#FF6B6B');
    }
  },

  // 角度转时间（支持30分钟颗粒度）
  angleToTime(angle) {
    // 0度对应12点方向（00:00），顺时针增加
    // 每30分钟对应7.5度
    const totalMinutes = Math.round(angle / 7.5) * 30;
    const hours = Math.floor(totalMinutes / 60) % 24;
    const minutes = totalMinutes % 60;
    return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
  },

  // 时间转角度（支持30分钟颗粒度）
  timeToAngle(time) {
    const [hourStr, minuteStr] = time.split(':');
    const hour = parseInt(hourStr);
    const minute = parseInt(minuteStr);
    const totalMinutes = hour * 60 + minute;
    // 每30分钟对应7.5度，0:00对应0度（12点方向）
    return (totalMinutes / 30 * 7.5) % 360;
  },

  // 判断时间选择逻辑并生成时间槽信息
  determineTimeSlot(selectedStartTime, selectedEndTime) {
    const now = new Date();
    const currentHour = now.getHours();
    const currentMinute = now.getMinutes();
    const currentTotalMinutes = currentHour * 60 + currentMinute;
    
    const [startHour, startMinute] = selectedStartTime.split(':').map(Number);
    const [endHour, endMinute] = selectedEndTime.split(':').map(Number);
    const startTotalMinutes = startHour * 60 + startMinute;
    const endTotalMinutes = endHour * 60 + endMinute;
    
    let startDate, endDate, displayText;
    
    // 确定开始日期
    if (startTotalMinutes <= currentTotalMinutes) {
      // 开始时间 <= 当前时间 → 次日
      startDate = 'tomorrow';
    } else {
      // 开始时间 > 当前时间 → 当天
      startDate = 'today';
    }
    
    // 确定结束日期
    if (endTotalMinutes <= startTotalMinutes) {
      // 结束时间 <= 开始时间，说明跨天
      if (startDate === 'today') {
        endDate = 'tomorrow';
        displayText = `${selectedStartTime}-次日${selectedEndTime}`;
      } else {
        // startDate === 'tomorrow'
        endDate = 'day-after-tomorrow';
        displayText = `次日${selectedStartTime}-后天${selectedEndTime}`;
      }
    } else {
      // 结束时间 > 开始时间，同一天
      endDate = startDate;
      if (startDate === 'today') {
        displayText = `${selectedStartTime}-${selectedEndTime}`;
      } else {
        displayText = `次日${selectedStartTime}-次日${selectedEndTime}`;
      }
    }
    
    return {
      startDate,
      endDate,
      displayText,
      actualStartTime: selectedStartTime,
      actualEndTime: selectedEndTime
    };
  },

  // 生成时间槽键值
  generateTimeSlotKey(startTime, endTime) {
    const now = new Date();
    const currentHour = now.getHours();
    const currentMinute = now.getMinutes();
    const currentTotalMinutes = currentHour * 60 + currentMinute;
    
    const [startHour, startMinute] = startTime.split(':').map(Number);
    const [endHour, endMinute] = endTime.split(':').map(Number);
    const startTotalMinutes = startHour * 60 + startMinute;
    const endTotalMinutes = endHour * 60 + endMinute;
    
    // 确定开始日期
    let startDate;
    if (startTotalMinutes <= currentTotalMinutes) {
      // 开始时间 <= 当前时间 → 次日
      startDate = new Date(now.getTime() + 24 * 60 * 60 * 1000);
    } else {
      // 开始时间 > 当前时间 → 当天
      startDate = now;
    }
    
    // 确定结束日期
    let endDate;
    if (endTotalMinutes <= startTotalMinutes) {
      // 结束时间 <= 开始时间，说明跨天到下一天
      endDate = new Date(startDate.getTime() + 24 * 60 * 60 * 1000);
    } else {
      // 结束时间 > 开始时间，同一天
      endDate = startDate;
    }
    
    const startDateStr = startDate.toISOString().split('T')[0];
    const endDateStr = endDate.toISOString().split('T')[0];
    
    // 生成包含完整日期信息的键值
    if (startDateStr === endDateStr) {
      // 同一天
      return `${startDateStr}_${startTime}-${endTime}`;
    } else {
      // 跨天
      return `${startDateStr}_${startTime}-${endDateStr}_${endTime}`;
    }
  },

  // 触摸事件处理
  async onTouchStart(e) {
    // 匹配状态下禁用拖拽
    if (this.data.isMatching) {
      return;
    }
    
    const { x, y } = await this.getTouchPosition(e);
    // 直接使用canvas的尺寸，与getTouchPosition保持一致
    const query = wx.createSelectorQuery().in(this);
    query.select('#timeCircle').boundingClientRect();
    query.exec((res) => {
      if (res[0]) {
        const rect = res[0];
        const canvasWidth = rect.width;
        const canvasHeight = rect.height;
        // 使用与drawTimeCircle相同的计算逻辑
        const containerWidth = Math.min(canvasWidth, canvasHeight);
        const outerDiameter = containerWidth - 32;
        const innerDiameter = outerDiameter - 128;
        const centerX = canvasWidth / 2;
        const centerY = canvasHeight / 2;
        const handleRadius = (outerDiameter + innerDiameter) / 4; // 圆环宽度中间位置
          
        // 计算开始和结束手柄的位置
        // 转换为Canvas坐标系统
        const startRad = (this.data.startAngle - 90) * Math.PI / 180;
        const endRad = (this.data.endAngle - 90) * Math.PI / 180;
        
        const startX = centerX + handleRadius * Math.cos(startRad);
        const startY = centerY + handleRadius * Math.sin(startRad);
        const endX = centerX + handleRadius * Math.cos(endRad);
        const endY = centerY + handleRadius * Math.sin(endRad);
        
        // 计算触摸点到手柄的距离
        const startDistance = Math.sqrt((x - startX) ** 2 + (y - startY) ** 2);
        const endDistance = Math.sqrt((x - endX) ** 2 + (y - endY) ** 2);
        
        // 判断是否点击了手柄（容差范围20px）
        const tolerance = 20;
        if (startDistance <= tolerance) {
          this.setData({
            isDragging: true,
            dragType: 'start'
          });
        } else if (endDistance <= tolerance) {
          this.setData({
            isDragging: true,
            dragType: 'end'
          });
        } else {
          this.setData({
            isDragging: false,
            dragType: ''
          });
        }
      }
    });
  },

  // 获取触摸位置
  async getTouchPosition(e) {
    return new Promise((resolve) => {
      const query = wx.createSelectorQuery().in(this);
      query.select('#timeCircle').boundingClientRect();
      query.exec((res) => {
        if (res[0]) {
          const rect = res[0];
          const x = e.touches[0].clientX - rect.left;
          const y = e.touches[0].clientY - rect.top;
          resolve({ x, y });
        }
      });
    });
  },

  async onTouchMove(e) {
    if (!this.data.isDragging) return;
    
    const { x, y } = await this.getTouchPosition(e);
    
    // 获取canvas尺寸信息
    const query = wx.createSelectorQuery().in(this);
    query.select('#timeCircle').boundingClientRect();
    query.exec((res) => {
      if (res[0]) {
        const rect = res[0];
        const canvasWidth = rect.width;
        const canvasHeight = rect.height;
        const centerX = canvasWidth / 2;
        const centerY = canvasHeight / 2;
        
        // 计算角度
        const angle = Math.atan2(y - centerY, x - centerX) * 180 / Math.PI;
        // 转换为我们的角度系统（12点为0度，顺时针增加）
        let normalizedAngle = (angle + 90 + 360) % 360;
        
        // 量化到30分钟间隔（7.5度间隔）
        normalizedAngle = Math.round(normalizedAngle / 7.5) * 7.5;
        
        // 更新对应的角度和时间
        if (this.data.dragType === 'start') {
          this.setData({
            startAngle: normalizedAngle,
            selectedStartTime: this.angleToTime(normalizedAngle)
          });
        } else if (this.data.dragType === 'end') {
          this.setData({
            endAngle: normalizedAngle,
            selectedEndTime: this.angleToTime(normalizedAngle)
          });
        }
        
        // 重新计算学习时长
        this.calculateStudyDuration();
        
        // 更新时间槽信息
        this.updateTimeSlot();
        
        // 重新绘制
        this.drawTimeCircle();
      }
    });
  },

  onTouchEnd() {
    this.setData({
      isDragging: false,
      dragType: ''
    });
  },

  // 更新时间槽信息
  updateTimeSlot() {
    const timeSlotInfo = this.determineTimeSlot(this.data.selectedStartTime, this.data.selectedEndTime);
    this.setData({
      timeSlotInfo: timeSlotInfo,
      selectedTimeSlot: timeSlotInfo.displayText
    });
  },

  // 检查登录状态
  async checkLoginStatus() {
    try {
      const result = await wx.cloud.callFunction({
        name: 'checkLogin',
        data: {}
      });
      
      console.log('检查登录状态结果:', result.result);
      
      if (result.result.code !== 0) {
        // 未登录，跳转到登录页
        wx.redirectTo({
          url: '/subpkg/pages/login/login'
        });
      }
    } catch (error) {
      console.error('检查登录状态失败:', error);
      // 出错时也跳转到登录页
      wx.redirectTo({
        url: '/subpkg/pages/login/login'
      });
    }
  },

  // 获取学习目标
  async getStudyGoal() {
    try {
      console.log('开始获取学习目标...');
      const result = await wx.cloud.callFunction({
        name: 'manageGoal',
        data: {
          action: 'get'
        }
      });
      
      console.log('获取学习目标结果:', result.result);
      
      if (result.result.code === 0 && result.result.data) {
        console.log('设置学习目标数据:', result.result.data);
        this.setData({
          studyGoal: result.result.data
        });
        
        // 计算剩余天数
        this.calculateGoalDaysLeft();
        console.log('学习目标设置完成，当前studyGoal:', this.data.studyGoal);
      } else {
        // 没有学习目标，显示添加目标状态
        console.log('没有学习目标，设置为null');
        this.setData({
          studyGoal: null,
          goalDaysLeft: 0
        });
        console.log('学习目标设置为null完成，当前studyGoal:', this.data.studyGoal);
      }
    } catch (error) {
      console.error('获取学习目标失败:', error);
      // 出错时也设置为null，显示添加目标状态
      this.setData({
        studyGoal: null,
        goalDaysLeft: 0
      });
      console.log('学习目标出错设置为null，当前studyGoal:', this.data.studyGoal);
    }
  },

  // 添加目标（点击无目标状态时调用）
  addGoal() {
    console.log('点击添加目标');
    this.showGoalModal();
  },

  // 编辑目标（点击编辑按钮时调用）
  editGoal() {
    console.log('点击编辑目标');
    this.showGoalModal();
  },

  // 显示目标设置弹窗
  showGoalModal() {
    if (this.data.studyGoal) {
      // 编辑现有目标
      this.setData({
        showGoalModal: true,
        isEditingGoal: true,
        tempGoalTitle: this.data.studyGoal.title,
        tempGoalDeadline: this.data.studyGoal.deadline,
        existingGoalData: this.data.studyGoal
      });
    } else {
      // 创建新目标
      this.setData({
        showGoalModal: true,
        isEditingGoal: false,
        tempGoalTitle: '',
        tempGoalDeadline: this.getDefaultDate(),
        existingGoalData: null
      });
    }
  },

  // 隐藏目标设置弹窗
  hideGoalModal() {
    this.setData({
      showGoalModal: false,
      tempGoalTitle: '',
      tempGoalDeadline: '',
      isEditingGoal: false,
      existingGoalData: null
    });
  },

  // 获取默认日期（明天）
  getDefaultDate() {
    const tomorrow = new Date();
    tomorrow.setDate(tomorrow.getDate() + 1);
    return tomorrow.toISOString().split('T')[0];
  },

  // 处理目标标题输入
  onGoalTitleInput(e) {
    this.setData({
      tempGoalTitle: e.detail.value
    });
  },

  // 处理目标截止日期选择
  onGoalDeadlineChange(e) {
    this.setData({
      tempGoalDeadline: e.detail.value
    });
  },

  // 兼容WXML中picker的bindchange="onDateChange"
  onDateChange(e) {
    // 复用现有逻辑，确保选择日期会写入 tempGoalDeadline
    this.onGoalDeadlineChange(e);
  },

  // 保存学习目标
  async saveGoal() {
    const { tempGoalTitle, tempGoalDeadline, isEditingGoal } = this.data;
    
    if (!tempGoalTitle.trim()) {
      wx.showToast({
        title: '请输入目标标题',
        icon: 'none'
      });
      return;
    }
    
    if (!tempGoalDeadline) {
      wx.showToast({
        title: '请选择截止日期',
        icon: 'none'
      });
      return;
    }
    
    // 检查截止日期是否在今天之后
    const today = new Date();
    const deadline = new Date(tempGoalDeadline);
    today.setHours(0, 0, 0, 0);
    deadline.setHours(0, 0, 0, 0);
    
    if (deadline <= today) {
      wx.showToast({
        title: '截止日期必须在今天之后',
        icon: 'none'
      });
      return;
    }
    
    try {
      wx.showLoading({
        title: isEditingGoal ? '更新中...' : '保存中...'
      });
      
      const goalId = isEditingGoal ? ((this.data.existingGoalData && this.data.existingGoalData._id) || (this.data.studyGoal && this.data.studyGoal._id)) : null;
      const result = await wx.cloud.callFunction({
        name: 'manageGoal',
        data: {
          action: isEditingGoal ? 'update' : 'add',
          goalData: {
            goalId: goalId,
            title: tempGoalTitle.trim(),
            deadline: tempGoalDeadline
          }
        }
      });
      
      wx.hideLoading();
      
      if (result.result.code === 0) {
        wx.showToast({
          title: isEditingGoal ? '目标更新成功' : '目标创建成功',
          icon: 'success'
        });
        
        // 更新本地数据，保留/回填 _id
        const existingId = (this.data.existingGoalData && this.data.existingGoalData._id) || (this.data.studyGoal && this.data.studyGoal._id);
        const newStudyGoal = isEditingGoal ? {
          _id: existingId,
          title: tempGoalTitle.trim(),
          deadline: tempGoalDeadline,
          status: 'active',
          progress: (this.data.studyGoal && this.data.studyGoal.progress) || 0
        } : {
          _id: (result.result.data && result.result.data.goalId) || null,
          title: tempGoalTitle.trim(),
          deadline: tempGoalDeadline,
          status: 'active',
          progress: 0
        };
        this.setData({
          studyGoal: newStudyGoal
        });
        
        // 重新计算剩余天数
        this.calculateGoalDaysLeft();
        
        // 隐藏弹窗
        this.hideGoalModal();
      } else {
        wx.showToast({
          title: result.result.msg || '操作失败',
          icon: 'none'
        });
      }
    } catch (error) {
      wx.hideLoading();
      console.error('保存学习目标失败:', error);
      wx.showToast({
        title: '操作失败，请重试',
        icon: 'none'
      });
    }
  },

  // 取消目标弹窗
  cancelGoalModal() {
    this.hideGoalModal();
  },

  // 确认保存目标
  confirmSaveGoal() {
    this.saveGoal();
  },

  // 阻止弹窗关闭
  preventModalClose() {
    // 阻止事件冒泡，防止点击弹窗内容时关闭弹窗
  },

  // 开始匹配
  async startMatching() {
    try {
      console.log('开始匹配，时间段:', this.data.selectedStartTime, '-', this.data.selectedEndTime);
      
      // 生成时间槽键值
      const timeSlotKey = this.generateTimeSlotKey(this.data.selectedStartTime, this.data.selectedEndTime);
      console.log('生成的时间槽键值:', timeSlotKey);
      
      // 设置匹配状态
      this.setData({
        isMatching: true,
        matchingSeconds: 0,
        matchingTime: '00:00',
        currentTimeSlotKey: timeSlotKey
      });
      
      // 重新绘制时间圆环（匹配状态下显示绿色）
      this.drawTimeCircle();
      
      // 调用云函数加入匹配池
      const result = await wx.cloud.callFunction({
        name: 'joinMatchingPool',
        data: {
          startTime: this.data.selectedStartTime,
          endTime: this.data.selectedEndTime,
          studyDuration: this.data.studyDuration
        }
      });
      
      console.log('加入匹配池结果:', result.result);
      
      if (result.result.code === 0) {
        // 检查是否直接匹配成功
        if (result.result.data && result.result.data.matched) {
          // 直接匹配成功，处理匹配数据
          const matchData = result.result.data;
          console.log('直接匹配成功，数据:', matchData);
          
          // 确保学习伙伴信息存在
          let partnerInfo = matchData.partnerInfo || {};
          if (!partnerInfo.nickName) {
            partnerInfo = {
              nickName: '学习伙伴',
              avatarUrl: '/static/icons/avatar-placeholder.png',
              ...partnerInfo
            };
          }
          
          // 从云函数返回的数据中提取关键信息（兼容旧结构）
          const studyRecordId = matchData.studyRecordId || matchData.matchRecordId;
          const matchId = matchData.matchId || matchData.matchRecordId;
          const matchTime = matchData.matchTime || {
            startTime: matchData.startTime,
            endTime: matchData.endTime,
            duration: matchData.duration
          };
          
          console.log('提取关键数据:');
          console.log('- studyRecordId:', studyRecordId);
          console.log('- matchId:', matchId);
          console.log('- matchTime:', matchTime);
          console.log('- 完整匹配数据:', matchData);
          
          // 确保关键数据存在
          if (!studyRecordId) {
            console.error('studyRecordId 缺失，完整匹配数据:', matchData);
            wx.showToast({
              title: '匹配数据异常，请重试',
              icon: 'error'
            });
            // 重置匹配状态
            this.setData({
              isMatching: false,
              matchingTime: '00:00',
              matchingSeconds: 0
            });
            this.drawTimeCircle();
            return;
          }
          
          // 设置匹配成功状态
          // 先将头像从 cloud:// 转为临时 https，再写入，避免首帧渲染 500
          const avatarRaw = this.normalizeAvatar(partnerInfo.avatarUrl || partnerInfo.avatar_url || partnerInfo.avatar);
          let avatar = '';
          try {
            avatar = await this.ensureHttpsAvatar(avatarRaw);
          } catch (e) {
            console.warn('ensureHttpsAvatar 转换失败:', e);
          }
          if (
            !(
              typeof avatar === 'string' &&
              (/^https?:\/\//i.test(avatar) ||
                avatar.indexOf('wxfile://') === 0 ||
                avatar.indexOf('/static/') === 0 ||
                avatar.indexOf('data:') === 0)
            )
          ) {
            avatar = '/static/icons/avatar-placeholder.png';
          }
          this.setData({
            isMatching: false,
            isMatchSuccess: true,
            studyRecordId: studyRecordId,
            matchId: matchId,
            selectedStartTime: matchTime.startTime,
            selectedEndTime: matchTime.endTime,
            studyDuration: matchTime.duration,
            matchedUser: {
              name: partnerInfo.nickName,
              avatar: avatar,
              isOnline: true,
              examName: 'CET-6',
              daysLeft: 28,
              examDate: '2025年12月21日'
            }
          });


          // 基于 matchId 的兜底：查询对端学习记录再取对方资料（带重试）
          if (matchId) {
            this.ensurePeerInfoByMatchIdWithRetry(matchId);
          }

          // 重新绘制时间圆环
          this.drawTimeCircle();
          
          // 显示匹配成功提示
          wx.showToast({
            title: '匹配成功！',
            icon: 'success'
          });
          
          console.log('直接匹配成功，设置完成后的数据:');
          console.log('- studyRecordId:', this.data.studyRecordId);
          console.log('- matchId:', this.data.matchId);
          console.log('- selectedStartTime:', this.data.selectedStartTime);
          console.log('- selectedEndTime:', this.data.selectedEndTime);
          console.log('- studyDuration:', this.data.studyDuration);
        } else {
          // 加入匹配池等待，开始匹配计时和轮询
          this.startMatchingTimer();
          this.startMatchingStatusCheck();
        }
      } else {
        // 加入匹配池失败，重置状态
        this.setData({
          isMatching: false,
          matchingTime: '00:00',
          matchingSeconds: 0
        });
        
        // 重新绘制时间圆环
        this.drawTimeCircle();
        
        wx.showToast({
          title: result.result.msg || '加入匹配池失败',
          icon: 'none'
        });
      }
    } catch (error) {
      console.error('开始匹配失败:', error);
      
      // 重置匹配状态
      this.setData({
        isMatching: false,
        matchingTime: '00:00',
        matchingSeconds: 0
      });
      
      // 重新绘制时间圆环
      this.drawTimeCircle();
      
      wx.showToast({
        title: '匹配失败，请重试',
        icon: 'none'
      });
    }
  },

  // 开始匹配计时器
  startMatchingTimer() {
    // 清除之前的计时器
    if (this.matchingTimer) {
      clearInterval(this.matchingTimer);
    }
    
    this.matchingTimer = setInterval(() => {
      const newSeconds = this.data.matchingSeconds + 1;
      const minutes = Math.floor(newSeconds / 60);
      const seconds = newSeconds % 60;
      const timeStr = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
      
      this.setData({
        matchingSeconds: newSeconds,
        matchingTime: timeStr
      });
    }, 1000);
  },

  // 开始轮询匹配状态
  startMatchingStatusCheck() {
    // 清除之前的轮询
    if (this.matchingStatusTimer) {
      clearInterval(this.matchingStatusTimer);
    }
    
    this.matchingStatusTimer = setInterval(async () => {
      try {
        const result = await wx.cloud.callFunction({
          name: 'checkMatchingStatus',
          data: {
            timeSlotKey: this.data.currentTimeSlotKey
          }
        });
        
        console.log('匹配状态检查结果:', result.result);
        
        if (result.result.code === 0 && result.result.data) {
          const matchData = result.result.data;
          
          if (matchData.status === 'matched') {
            // 匹配成功
            console.log('匹配成功！学习记录ID:', matchData.studyRecordId);
            
            // 停止计时器和轮询
            if (this.matchingTimer) {
              clearInterval(this.matchingTimer);
              this.matchingTimer = null;
            }
            if (this.matchingStatusTimer) {
              clearInterval(this.matchingStatusTimer);
              this.matchingStatusTimer = null;
            }
            
            // 更新状态为匹配成功
            // 确保匹配用户信息存在，避免空对象引用错误（兼容 matchedUser 字段）
            let partnerInfo = matchData.partnerInfo || matchData.matchedUser || {};
            
            console.log('匹配成功数据:', matchData);
            console.log('学习记录ID:', matchData.studyRecordId);
            console.log('匹配ID:', matchData.matchId);
            console.log('开始时间:', matchData.startTime);
            console.log('结束时间:', matchData.endTime);
            console.log('学习时长:', matchData.duration);
            
            // 确保所有必要数据都存在（兼容不同返回结构）
            const studyRecordId = matchData.studyRecordId || matchData.matchRecordId;
            const matchId = matchData.matchId || matchData.matchRecordId;
            // 兼容时间字段：优先 matchTime，其次顶层，再从 timeSlotKey 解析
            let startTime = (matchData.matchTime && matchData.matchTime.startTime) || matchData.startTime;
            let endTime = (matchData.matchTime && matchData.matchTime.endTime) || matchData.endTime;
            let duration = (matchData.matchTime && matchData.matchTime.duration) || matchData.duration;
            if ((!startTime || !endTime) && matchData.timeSlotKey) {
              const parts = String(matchData.timeSlotKey).split('_');
              const range = parts[parts.length - 1];
              if (range && range.includes('-')) {
                const [st, et] = range.split('-');
                startTime = startTime || st;
                endTime = endTime || et;
              }
            }
            if (!duration && startTime && endTime) {
              const [sh, sm] = startTime.split(':').map(Number);
              const [eh, em] = endTime.split(':').map(Number);
              const sMin = sh * 60 + sm;
              let eMin = eh * 60 + em;
              if (eMin <= sMin) eMin += 24 * 60;
              duration = ((eMin - sMin) / 60).toFixed(1);
            }
            
            if (!studyRecordId) {
              console.error('studyRecordId 为空，匹配数据异常');
              wx.showToast({
                title: '匹配数据异常，请重试',
                icon: 'none'
              });
              return;
            }
            
            // 先将头像从 cloud:// 转为临时 https，再写入，避免首帧渲染 500
            const avatarRaw = this.normalizeAvatar(partnerInfo.avatarUrl || partnerInfo.avatar_url || partnerInfo.avatar);
            let avatar = '';
            try {
              avatar = await this.ensureHttpsAvatar(avatarRaw);
            } catch (e) {
              console.warn('ensureHttpsAvatar 转换失败:', e);
            }
            if (
              !(
                typeof avatar === 'string' &&
                (/^https?:\/\//i.test(avatar) ||
                  avatar.indexOf('wxfile://') === 0 ||
                  avatar.indexOf('/static/') === 0 ||
                  avatar.indexOf('data:') === 0)
              )
            ) {
              avatar = '/static/icons/avatar-placeholder.png';
            }
            this.setData({
              isMatching: false,
              isMatchSuccess: true,
              studyRecordId: studyRecordId,
              matchId: matchId,
              selectedStartTime: startTime,
              selectedEndTime: endTime,
              studyDuration: duration,
              matchedUser: {
                name: partnerInfo.nickName || '学习伙伴',
                avatar: avatar,
                isOnline: true,
                examName: 'CET-6',
                daysLeft: 28,
                examDate: '2025年12月21日'
              }
            });


            // 基于 matchId 的兜底：查询对端学习记录再取对方资料覆盖 matchedUser（轮询分支，带重试）
            if (matchId) {
              console.log('通过 matchId 拉取对端资料（轮询分支）:', matchId);
              this.ensurePeerInfoByMatchIdWithRetry(matchId);
            }
            
            console.log('设置完成后的数据:');
            console.log('- studyRecordId:', this.data.studyRecordId);
            console.log('- matchId:', this.data.matchId);
            console.log('- selectedStartTime:', this.data.selectedStartTime);
            console.log('- selectedEndTime:', this.data.selectedEndTime);
            console.log('- studyDuration:', this.data.studyDuration);
            
            // 重新绘制时间圆环
            this.drawTimeCircle();
            
            // 显示匹配成功提示
            wx.showToast({
              title: '匹配成功！',
              icon: 'success'
            });
          }
        }
      } catch (error) {
        console.error('检查匹配状态失败:', error);
      }
    }, 2000); // 每2秒检查一次
  },

  // 基于 matchId 的兜底：查询对端学习记录并取对方资料覆盖 matchedUser（含 fallback 到 fetchPeerByMatchId）
  async ensurePeerInfoByMatchId(matchId) {
    try {
      // 如果当前 matchedUser 已不是默认（既有非“学习伙伴”名字，且头像非占位），则不覆盖
      const nameIsDefault = !this.data.matchedUser || !this.data.matchedUser.name || this.data.matchedUser.name === '学习伙伴';
      const avatarIsDefault =
        !this.data.matchedUser || !this.data.matchedUser.avatar || String(this.data.matchedUser.avatar).indexOf('avatar-placeholder') !== -1;

      if (!nameIsDefault && !avatarIsDefault) return;
      if (!matchId) return;

      console.log('通过 matchId 拉取对端资料:', matchId);

      let pi = null;

      // 优先：getStudyRecord(peerByMatchId)
      try {
        const res = await wx.cloud.callFunction({
          name: 'getStudyRecord',
          data: { action: 'peerByMatchId', matchId }
        });
        if (res && res.result && res.result.code === 0 && res.result.data && res.result.data.partnerInfo) {
          pi = res.result.data.partnerInfo;
        }
      } catch (e1) {
        console.warn('getStudyRecord peerByMatchId 调用失败:', e1);
      }

      // 回退：fetchPeerByMatchId
      if (!pi) {
        try {
          const res2 = await wx.cloud.callFunction({
            name: 'fetchPeerByMatchId',
            data: { matchId }
          });
          if (res2 && res2.result && res2.result.code === 0 && res2.result.data && res2.result.data.partnerInfo) {
            pi = res2.result.data.partnerInfo;
          }
        } catch (e2) {
          console.warn('fetchPeerByMatchId 调用失败:', e2);
        }
      }

      if (pi) {
        const name = pi.nickName || pi.nickname || this.data.matchedUser.name || '学习伙伴';
        let avatar = this.normalizeAvatar(pi.avatarUrl || pi.avatar_url || pi.avatar || this.data.matchedUser.avatar);
        try {
          avatar = await this.ensureHttpsAvatar(avatar);
        } catch (e3) {
          console.warn('ensureHttpsAvatar 转换失败:', e3);
        }
        this.setData({
          'matchedUser.name': name,
          'matchedUser.avatar': avatar
        });
      }
    } catch (e) {
      console.warn('ensurePeerInfoByMatchId 失败:', e);
    }
  },

  // 基于 matchId 的兜底（带重试）：对端记录未落库或资料未就绪时，进行有限次重试
  async ensurePeerInfoByMatchIdWithRetry(matchId) {
    try {
      const delays = [800, 1500, 2500];
      for (let i = 0; i < delays.length; i++) {
        await this.ensurePeerInfoByMatchId(matchId);
        const nameIsDefault = !this.data.matchedUser || !this.data.matchedUser.name || this.data.matchedUser.name === '学习伙伴';
        const avatarIsDefault =
          !this.data.matchedUser ||
          !this.data.matchedUser.avatar ||
          String(this.data.matchedUser.avatar).indexOf('avatar-placeholder') !== -1;
        if (!nameIsDefault && !avatarIsDefault) {
          return;
        }
        await new Promise((resolve) => setTimeout(resolve, delays[i]));
      }

      // 仍未获取到真实资料，兜底占位图与默认昵称
      const hasAvatar = this.data.matchedUser && this.data.matchedUser.avatar;
      const hasName = this.data.matchedUser && this.data.matchedUser.name;
      const placeholder = '/static/icons/avatar-placeholder.png';
      if (!hasAvatar) {
        console.warn('ensurePeerInfoByMatchIdWithRetry: 使用占位头像兜底');
        this.setData({ 'matchedUser.avatar': placeholder });
      }
      if (!hasName) {
        this.setData({ 'matchedUser.name': '学习伙伴' });
      }
    } catch (e) {
      console.warn('ensurePeerInfoByMatchIdWithRetry 失败:', e);
      const placeholder = '/static/icons/avatar-placeholder.png';
      if (!this.data.matchedUser || !this.data.matchedUser.avatar) {
        this.setData({ 'matchedUser.avatar': placeholder });
      }
      if (!this.data.matchedUser || !this.data.matchedUser.name) {
        this.setData({ 'matchedUser.name': '学习伙伴' });
      }
    }
  },

  // 取消匹配
  async cancelMatching() {
    try {
      console.log('取消匹配');
      
      // 调用云函数离开匹配池
      const result = await wx.cloud.callFunction({
        name: 'leaveMatchingPool',
        data: {
          timeSlotKey: this.data.currentTimeSlotKey
        }
      });
      
      console.log('离开匹配池结果:', result.result);
      
      // 停止计时器和轮询
      if (this.matchingTimer) {
        clearInterval(this.matchingTimer);
        this.matchingTimer = null;
      }
      if (this.matchingStatusTimer) {
        clearInterval(this.matchingStatusTimer);
        this.matchingStatusTimer = null;
      }
      
      // 重置匹配状态
      this.setData({
        isMatching: false,
        matchingTime: '00:00',
        matchingSeconds: 0,
        currentTimeSlotKey: ""
      });
      
      // 重新绘制时间圆环
      this.drawTimeCircle();
      
      if (result.result.code === 0) {
        wx.showToast({
          title: '已取消匹配',
          icon: 'success'
        });
      }
    } catch (error) {
      console.error('取消匹配失败:', error);
      
      // 即使云函数调用失败，也要重置本地状态
      if (this.matchingTimer) {
        clearInterval(this.matchingTimer);
        this.matchingTimer = null;
      }
      if (this.matchingStatusTimer) {
        clearInterval(this.matchingStatusTimer);
        this.matchingStatusTimer = null;
      }
      
      this.setData({
        isMatching: false,
        matchingTime: '00:00',
        matchingSeconds: 0,
        currentTimeSlotKey: ""
      });
      
      this.drawTimeCircle();
      
      wx.showToast({
        title: '已取消匹配',
        icon: 'success'
      });
    }
  },

  // 开始学习
  async startStudy() {
    try {
      console.log('开始学习方法调用');
      console.log('当前页面数据:', {
        studyRecordId: this.data.studyRecordId,
        matchId: this.data.matchId,
        isMatchSuccess: this.data.isMatchSuccess,
        selectedStartTime: this.data.selectedStartTime,
        selectedEndTime: this.data.selectedEndTime
      });
      
      // 检查必要参数
      if (!this.data.studyRecordId) {
        console.error('studyRecordId 为空，无法开始学习');
        console.error('完整的页面数据:', this.data);
        
        wx.showToast({
          title: '学习记录丢失，请重新匹配',
          icon: 'none'
        });
        
        // 重置状态，让用户重新匹配
        this.setData({
          isMatchSuccess: false,
          isMatching: false,
          studyRecordId: null,
          matchId: null
        });
        this.drawTimeCircle();
        return;
      }
      
      // 直接跳转到学习页面，因为学习记录已经在匹配成功时创建了
      console.log('跳转到学习页面，studyRecordId:', this.data.studyRecordId);
      wx.navigateTo({
        url: `/subpkg/pages/study/study?studyRecordId=${this.data.studyRecordId}`
      });
    } catch (error) {
      console.error('开始学习失败:', error);
      wx.showToast({
        title: '开始学习失败，请重试',
        icon: 'none'
      });
    }
  },

  // 退出学习
  async exitStudy() {
    wx.showModal({
      title: '确认退出',
      content: '确定要退出当前学习吗？退出后将无法恢复学习记录。',
      confirmText: '确定退出',
      cancelText: '取消',
      success: async (res) => {
        if (res.confirm) {
          try {
            wx.showLoading({
              title: '退出中...'
            });
            
            // 调用云函数删除学习记录
            const result = await wx.cloud.callFunction({
              name: 'deleteStudyRecord',
              data: {
                studyRecordId: this.data.studyRecordId
              }
            });
            
            wx.hideLoading();
            
            console.log('删除学习记录结果:', result.result);
            
            if (result.result.code === 0) {
              // 重置为未匹配状态
              this.setData({
                isMatchSuccess: false,
                isMatching: false,
                studyRecordId: null,
                matchId: null,
                matchingTime: '00:00',
                matchingSeconds: 0
              });
              
              // 重新绘制时间圆环
              this.drawTimeCircle();
              
              wx.showToast({
                title: '已退出学习',
                icon: 'success'
              });
            } else {
              wx.showToast({
                title: result.result.msg || '退出失败',
                icon: 'none'
              });
            }
          } catch (error) {
            wx.hideLoading();
            console.error('退出学习失败:', error);
            wx.showToast({
              title: '退出失败，请重试',
              icon: 'none'
            });
          }
        }
      }
    });
  },

  // 去广场看看
  goToPlaza() {
    console.log('点击去广场看看按钮');
    wx.navigateTo({
      url: '/subpkg/pages/plaza/plaza',
      fail: (error) => {
        console.error('跳转广场页面失败:', error);
        wx.showToast({
          title: '跳转失败，请重试',
          icon: 'none'
        });
      }
    });
  },

  // 页面卸载时清理计时器
  onUnload() {
    if (this.matchingTimer) {
      clearInterval(this.matchingTimer);
      this.matchingTimer = null;
    }
    if (this.matchingStatusTimer) {
      clearInterval(this.matchingStatusTimer);
      this.matchingStatusTimer = null;
    }
    if (this.onlinePingTimer) {
      console.log('onUnload: stopOnlineHeartbeat, timer=', this.onlinePingTimer);
      clearInterval(this.onlinePingTimer);
      this.onlinePingTimer = null;
    } else {
      console.log('onUnload: stopOnlineHeartbeat skipped (no timer)');
    }
  }
});

